package org.smartopen.unionpay.openapi.listener.mq.impl;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.smartframework.core.util.StrUtil;
import org.smartframework.unionpay.constant.PayConstant;
import org.smartframework.unionpay.domain.SmartPayNotifyResult;
import org.smartframework.unionpay.domain.SmartRefundNotifyResult;
import org.smartframework.unionpay.entity.RefundOrder;
import org.smartframework.unionpay.service.IRefundOrderService;
import org.smartopen.unionpay.openapi.constant.MqConstants;
import org.smartopen.unionpay.openapi.listener.mq.IUnionPayNotify;
import org.smartopen.unionpay.openapi.service.IMqService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;

@Component
@Slf4j
@RequiredArgsConstructor
public class UnionPayRefundNotifyListener implements IUnionPayNotify<SmartRefundNotifyResult> {

    @Getter
    private final String queueName = MqConstants.UNIONPAY_PAY_NOTIFY_QUEUE_NAME;

    private final IRefundOrderService refundOrderService;
    @Getter
    private final RestTemplate restTemplate;
    @Getter
    private final IMqService mqService;

    /**
     * 支付回调
     */
    @RabbitListener(queues = MqConstants.UNIONPAY_REFUND_NOTIFY_QUEUE_NAME)
    public void onMessage(SmartRefundNotifyResult result) {
        //更新次数
        final RefundOrder refundOrder = this.updateNotify(result.getOrgId(), result.getOutTradeNo());
        final String notifyUrl = refundOrder.getNotifyUrl();

        if (StrUtil.isEmpty(notifyUrl)) return;

        String ret = this.sendNotifyUrl(notifyUrl, result);
        if (!PayConstant.RETURN_VALUE_SUCCESS.equalsIgnoreCase(ret)) {
            this.sendMessage(result, refundOrder.getNotifyCount());
        }
    }


    /**
     * 支付失败
     *
     * @return
     */
    public RefundOrder updateNotify(String orgId, String outTradeNo) {
        synchronized (orgId + outTradeNo) {
            final RefundOrder refundOrder = refundOrderService.queryOrder(orgId, outTradeNo);
            this.refundOrderService.lambdaUpdate()
                    .set(RefundOrder::getNotifyLastTime, LocalDateTime.now())
                    .set(RefundOrder::getNotifyCount, refundOrder.getNotifyCount() + 1)
                    .eq(RefundOrder::getId, refundOrder.getId()).update();
            return refundOrder;
        }
    }

}